﻿/*
    This file is part of News Worm.

    News Worm is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    News Worm is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with News Worm.  If not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.ServiceModel.Syndication;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace NewsWorm {
    public partial class MainWindow : Form, IMainWindowClient {
        public MainWindow( string path ) {
            InitApp( path );
        }

        public MainWindow( string path, string url ) {
            InitApp( path );
            m_OnLaunchAddUrl = url;
        }

        private void InitApp( string path ) {
            InitializeComponent();
            FeedTree.Font = SystemFonts.MessageBoxFont;
            m_Path = path;
            m_RegistryManager = new RegistryManager( path );
  
            DisableButtonsAndMenus();
            statusBarPanelLeft.Text = " ";
            FeedTree.ContextMenu = this.ContextMenuItems;

            //No need to create feed manager here. It will be create OnShown using load.
            //m_FeedManager = new FeedManager(m_Path, m_RegistryManager);
            m_Timer = new System.Windows.Forms.Timer();

            int milliseconds = GetCurrentMilliSecondsFromSettings();
            m_Timer.Interval = milliseconds;

            m_Timer.Tick += m_Timer_Tick;

            m_SearchManager = new SearchManager();
            FeedTree.ImageIndex = NONODEIMAGE;
            FeedTree.SelectedImageIndex = NONODEIMAGE;
            toolBarButtonStar.Enabled = false;
            toolBarButtonCreateFromSearch.Enabled = false;
            m_TreeState = new TreeViewState( m_Path );
            m_RuntimeExpansionMemoryList = new List<string>();
            NewsWorm.NativeMethods.SetWindowTheme( FeedTree.Handle, "explorer", null );

            this.notifyIconNewsWorm.ContextMenu = contextMenuTray;

            if ( Properties.Settings.Default.MinimizeToTray || Properties.Settings.Default.NewArticleNotification )
                notifyIconNewsWorm.Visible = true;
            else
                notifyIconNewsWorm.Visible = false;

            m_ScriptingEvents = new ScriptingEvents();

            m_TimerStatusBar = new System.Windows.Forms.Timer();
            m_TimerStatusBar.Interval = 1500;
            m_TimerStatusBar.Tick += m_TimerStatusBar_Tick;
            this.Font = SystemFonts.MessageBoxFont;
        }

        //Fit our clear button to the search box
        protected override void OnLoad( EventArgs e ) {
            Button btn = new Button();
            btn.FlatStyle = FlatStyle.Flat;
            btn.FlatAppearance.BorderSize = 0;
            btn.FlatAppearance.MouseOverBackColor = Color.Transparent;
            btn.FlatAppearance.MouseDownBackColor = Color.Transparent;

            btn.MouseHover += ClearSearchButton_MouseHover;
            btn.Click += ClearSearchButton_Click;

            btn.Size = new Size( 25, this.textBoxSearch.ClientSize.Height + 2 );
            btn.Location = new Point( this.textBoxSearch.ClientSize.Width - btn.Width, -1 );
            btn.Cursor = Cursors.Default;
            btn.Image = this.imageListButtons.Images["broom.png"];

            btn.Cursor = Cursors.Hand;

            this.textBoxSearch.Controls.Add( btn );

            // Send EM_SETMARGINS to prevent text from disappearing underneath the button
            NewsWorm.NativeMethods.SendMessage( this.textBoxSearch.Handle, 0xd3, (IntPtr)2, (IntPtr)( btn.Width << 16 ) );

            base.OnLoad( e );
        }

        private void ClearSearch() {

            if ( m_SearchActive ) {

                this.SuspendLayout();
                m_CanSearch = false;
                textBoxSearch.ForeColor = Color.Gray;
                textBoxSearch.Text = "Type to search";

                List<string> ReadItemsInSearchView = new List<string>();

                foreach ( TreeNode root in FeedTree.Nodes ) {
                    foreach ( TreeNode node in root.Nodes ) {
                        if ( m_FeedManager.VisitedItems.ContainsKey( node.Name ) )
                            ReadItemsInSearchView.Add( node.Name );
                    }
                }

                FeedTree.Nodes.Clear();

                foreach ( TreeNode node in m_SearchManager.OldNodes ) {

                    if ( !FeedTree.Nodes.Contains( node ) ) {

                        //Check if article is marked as read in the search view
                        foreach ( TreeNode subNode in node.Nodes ) {
                            if ( m_FeedManager.VisitedItems.ContainsKey( subNode.Name ) )
                                subNode.ForeColor = Color.BlueViolet;
                        }

                        FeedTree.Nodes.Add( node );
                    }
                }

                if ( Properties.Settings.Default.HideReadItems ) {
                    foreach ( TreeNode node in m_SearchManager.OldReadNodes )
                        if ( !FeedTree.Nodes.Contains( node ) )
                            FeedTree.Nodes.Add( node );
                }

                m_SearchManager.ClearBackupNodes();

                FeedTree.Focus();
                m_Timer.Start();

                if ( Properties.Settings.Default.HideReadItems )
                    HideReadItems();

                this.ResumeLayout();

                m_SearchActive = false;
                toolBarButtonCreateFromSearch.Enabled = false;
                m_CanSearch = true;
            }
        }

        private void ClearSearchButton_Click( object sender, EventArgs e ) {
            ClearSearch();
        }

        private void ClearSearchButton_MouseHover( object sender, EventArgs e ) {
            Button b = (Button)sender;
            int VisibleTime = 800;  //in milliseconds

            ToolTip tt = new ToolTip();
            tt.InitialDelay = 0;
            tt.Show( "Click to clear search (ESC)",
                b, 20, b.Height, VisibleTime );
        }

        private IFeedManager m_FeedManager;
        private int m_FeedCount = 0;
        private string m_Path;
        private System.Windows.Forms.Timer m_Timer;
        private SearchManager m_SearchManager;
        private const int NONODEIMAGE = 3;
        private const int NODEIMAGESTAR = 0;
        private TreeViewState m_TreeState;
        private string m_OnLaunchAddUrl = null;
        private RegistryManager m_RegistryManager;
        private List<string> m_RuntimeExpansionMemoryList;
        private Boolean m_CanModifyRuntimeExpansionMemoryList = true;
        private bool m_CanSearch = true;
        private bool m_SearchActive = false;
        private IScriptManager m_ScriptManager;
        private static int WM_QUERYENDSESSION = 0x11;
        private static bool m_SystemShutdown = false;
        private bool m_NoLicenceUserCancel = false;
        private string m_OldStatusBarLeftText;
        private bool m_IsSyncOnGoing = false;
        delegate void SetStatusLeftTextCallback( string text );
        delegate void SetStatusRightTextCallback( string text );
        delegate void RefreshFeedDisplayCallback();
        delegate void SetNotificationMessageCallback( string text );
        private bool m_FormClosing = false;
        private FormWindowState m_LastWindowStateBeforeMinimize = FormWindowState.Normal;
        private bool m_IsCustomFeedSyncOnGoing = false;
        private ScriptingEvents m_ScriptingEvents;
        private System.Windows.Forms.Timer m_TimerStatusBar;

        protected override void WndProc( ref Message m ) {
            if ( m.Msg == WM_QUERYENDSESSION ) {
                m_SystemShutdown = true;
                SaveSettingsAndFeeds();
                SaveProperties();
            }
            base.WndProc( ref m );
        }

        private int GetCurrentMilliSecondsFromSettings() {
            double minutes;
            double milliseconds;

            minutes = Properties.Settings.Default.FeedRefreshInterval;

            //We used to support interval less than 5 minutes.
            //This is a workaround for it.
            if ( minutes < 5 ) {
                minutes = 5;
                Properties.Settings.Default.FeedRefreshInterval = 5;
            }

            milliseconds = TimeSpan.FromMinutes( minutes ).TotalMilliseconds;

            return (int)milliseconds;
        }

        private void InitFavoriteNodes() {
            TreeNode root = new TreeNode();
            root.NodeFont = new Font( FeedTree.Font, FontStyle.Bold );
            root.Text = "Favorites         ";
            root.Name = "fav";
            root.ImageIndex = NODEIMAGESTAR;
            root.SelectedImageIndex = NODEIMAGESTAR;

            foreach ( FavoriteItem item in m_FeedManager.StarredItems ) {
                TreeNode node = new TreeNode();
                node.Name = item.Url;
                node.Text = item.Title;
                root.Nodes.Add( node );
            }

            FeedTree.Nodes.Add( root );
        }

        private void RefreshDisplayHelper() {
            RefreshFeedDisplay();
        }

        private void SetStatusLeftText( string text ) {
            m_OldStatusBarLeftText = statusBarPanelLeft.Text;
            statusBarPanelLeft.Text = text;
        }

        private void SetStatusRightText( string text ) {
            statusBarPanelRight.Text = text;
        }

        private void SetAndShowNotificationMessage( string text ) {
            if ( text.Length > 0 ) {
                notifyIconNewsWorm.BalloonTipTitle = "News Worm";
                notifyIconNewsWorm.BalloonTipText = text;
                notifyIconNewsWorm.ShowBalloonTip( 5000 );
             
            }
        }

        private void ResetStatusLeftText( string text ) {
            statusBarPanelLeft.Text = text;
        }

        private void SyncAllFeeds() {
            if ( !m_SearchActive ) {
                if ( !m_IsSyncOnGoing ) {
                    m_IsSyncOnGoing = true;
                    if ( MainStatusBar.InvokeRequired ) {
                        SetStatusLeftTextCallback d = new SetStatusLeftTextCallback( SetStatusLeftText );
                        this.Invoke( d, new object[] { "Syncing all feeds..." } );
                    } else {
                        m_OldStatusBarLeftText = statusBarPanelLeft.Text;
                        statusBarPanelLeft.Text = "Syncing all feeds...";
                    }

                    try {

                        List<NonCachedItem> list = m_FeedManager.RefreshAll();

                        if ( Properties.Settings.Default.NewArticleNotification ) {
                            string message = "";
                            //RefreshAll might return null on failure
                            if ( list != null ) {
                                if ( list.Count > 0 ) {
                                    //Something like Feed.Title: n new articles
                                    foreach ( NonCachedItem item in list ) {
                                        if ( item.HasNotificationEnabled ) {
                                            message += item.GetTruncatedFeedTitle() +
                                                       ": " + item.ArticleCount +
                                                       " new articles" +
                                                       Environment.NewLine;
                                        }
                                    }

                                    if ( this.InvokeRequired ) {
                                        SetNotificationMessageCallback d =
                                            new SetNotificationMessageCallback( SetAndShowNotificationMessage );
                                        this.Invoke( d, new object[] { message } );
                                    } else {
                                        SetAndShowNotificationMessage( message );
                                    }
                                  
                                    if ( Properties.Settings.Default.SpokenNotifications ) {
                                        NotificationSynthesis.Speak( list.Count.ToString() + " new articles available" );
                                    }
                                }
                            }
                        }

                    } catch ( Exception ex ) {
                        System.Console.Write( ex.Message );
                    }

                    if ( MainStatusBar.InvokeRequired ) {
                        SetStatusLeftTextCallback d = new SetStatusLeftTextCallback( ResetStatusLeftText );
                        this.Invoke( d, new object[] { m_OldStatusBarLeftText } );
                    } else {
                        statusBarPanelLeft.Text = m_OldStatusBarLeftText;
                    }

                    if ( FeedTree.InvokeRequired ) {
                        RefreshFeedDisplayCallback d = new RefreshFeedDisplayCallback( RefreshDisplayHelper );
                        this.Invoke( d );
                    } else {
                        RefreshFeedDisplay();
                    }

                    m_IsSyncOnGoing = false;
                }
            }
        }

        private void m_Timer_Tick( object sender, EventArgs e ) {
            new Thread(SyncAllFeeds).Start();
        }

        private void DisableButtonsAndMenus() {
            toolBarButtonRefresh.Enabled = false;
            toolBarButtonRemove.Enabled = false;
            menuItemRefresh.Enabled = false;
            menuItemRemove.Enabled = false;
            toolBarButtonStar.Enabled = false;
            menuItemFetchFeed.Enabled = false;
            toolBarButtonOpenBrowser.Enabled = false;
            toolBarButtonCopyUrl.Enabled = false;
        }

        private void MainToolBar_ButtonClick( object sender, ToolBarButtonClickEventArgs e ) {
            switch ( e.Button.Name ) {
                case "toolBarButtonAdd":
                    AddFeed();
                    break;
                case "toolBarButtonRemove":
                    RemoveFeed();
                    break;
                case "toolBarButtonRefresh":
                    RefreshFeed( Properties.Settings.Default.ArticlesToFetch );
                    break;
                case "toolBarButtonAsRead":
                    if ( !e.Button.Pushed ) {
                        ShowReadItems();
                        Properties.Settings.Default.HideReadItems = false;
                    } else {
                        HideReadItems();
                        Properties.Settings.Default.HideReadItems = true;
                    }
                    break;
                case "toolBarButtonStar":
                    MarkAsFavorite();
                    toolBarButtonStar.Enabled = false;
                    break;
                case "toolBarButtonOpenBrowser":
                    OpenInBrowser();
                    break;
                case "toolBarButtonCopyUrl":
                    CopyLink();
                    break;
                case "toolBarButtonExpand":
                    ExpandAll();
                    break;
                case "toolBarButtonCollapse":
                    CollapseAll();
                    break;
                case "toolBarButtonCreateFromSearch":
                    this.Cursor = Cursors.WaitCursor;
                    CreateFeedFromSearchResults();
                    this.Cursor = Cursors.Default;
                    break;
            }
        }

        private void CreateFeedFromSearchResults() {
            try {
                if ( m_SearchActive ) {
                    CreateCustomFeedDialog dlg = new CreateCustomFeedDialog();
                    if ( dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK ) {
                        this.Cursor = Cursors.WaitCursor;
                        statusBarPanelRight.Text = "Creating feed " + dlg.Title + "...";
                        List<string> Urls = new List<string>();
                        string title = "";
                        string SearchTerm = this.textBoxSearch.Text.Trim();
                        foreach ( TreeNode node in FeedTree.Nodes ) {
                            if ( node.Name != "fav" ) {
                                if ( node.Level == 0 ) {
                                    Feed feed = m_FeedManager.GetFeedByTitle( node.Name );
                                    if ( !feed.IsCustomSearchFeed ) {
                                        Urls.Add( feed.Url );
                                    }
                                }
                            }
                        }
                        ClearSearch();
                        //check that title with this name does not exist, if yes, append with "copy"
                        title = dlg.Title.Trim();
                        foreach ( TreeNode Node in FeedTree.Nodes ) {
                            if ( Node.Name.Equals( title ) ) {
                                title += " (Copy)";
                            }
                        }
                        CombinedSearchFeed CombinedFeed = new CombinedSearchFeed( Urls, SearchTerm, title,
                            Properties.Settings.Default.ArticlesToFetch, Guid.NewGuid().ToString(),m_ScriptingEvents);
                        Feed f = new Feed( CombinedFeed );
                        m_FeedManager.Add( f );
                        RefreshFeedDisplay( true, f );
                        this.Cursor = Cursors.Default;
                        statusBarPanelRight.Text = "";
                    }
                }
            } catch ( Exception ex ) {
                new MyMessageBoxError( ex.Message, ex.StackTrace ).ShowDialog();
            }
        }

        private void ExpandAll() {
            int index = 0;

            if ( FeedTree.SelectedNode != null )
                if ( FeedTree.SelectedNode.Level == 0 )
                    index = FeedTree.SelectedNode.Index;

            FeedTree.ExpandAll();
            FeedTree.SelectedNode = FeedTree.Nodes[index];
        }

        private void CollapseAll() {
            int index = 0;
            
            if ( FeedTree.SelectedNode != null )
                if(FeedTree.SelectedNode.Level == 0)
                    index = FeedTree.SelectedNode.Index;

            FeedTree.CollapseAll();

            FeedTree.SelectedNode = FeedTree.Nodes[index];
        }

        private void ShowReadItems() {
            //key parent, value node
            foreach ( KeyValuePair<string, Dictionary<TreeNode, int>> kvp in TreeViewHelper.ReadNodesHidden ) {
                foreach ( KeyValuePair<TreeNode, int> k in kvp.Value ) {

                    string key = kvp.Key;
                    int index = k.Value;
                    TreeNode value = k.Key;

                    TreeNode parent = FeedTree.Nodes.Find( key, true )[0];

                    if ( parent.Nodes.Count < index )
                        index = parent.Nodes.Count;

                    parent.Nodes.Insert( index, value );
                }
            }
        }

        //Store removed items somewhere and add them back in ShowReadItems
        private void HideReadItems() {
            this.Cursor = Cursors.WaitCursor;
            TreeViewHelper.ReadNodesHidden.Clear();

            //Let's have a temporary list of items to be removed.
            List<TreeNode> NodesToRemove = new List<TreeNode>();

            foreach ( KeyValuePair<string, string> kvp in
                m_FeedManager.VisitedItems ) {
                foreach ( Feed feed in m_FeedManager.Feeds ) {
                    foreach ( FeedItem item in feed.Items ) {
                        if ( item.Url.Equals( kvp.Key ) ) {
                            TreeNode[] nodes = FeedTree.Nodes.Find( item.Url, true );

                            foreach ( TreeNode n in nodes ) {
                                if ( n.Parent.Name != "fav" ) {
                                    TreeViewHelper.AddNodeToReadNodes( n.Parent.Name, n, n.Index );
                                    NodesToRemove.Add( n );
                                }
                            }
                        }
                    }
                }
            }

            //Now, let's remove the nodes from the view.
            //we have to do it in a separate loop to keep AddNodeToReadNodes index in sync
            foreach ( TreeNode n in NodesToRemove )
                FeedTree.Nodes.Remove( n );

            this.Cursor = Cursors.Default;
        }

        private void AddFeed( string url = null ) {
            AddFeedDialog dlg = new AddFeedDialog( m_FeedManager );
            bool added = false;
            Feed feed = null;

            if ( url != null )
                dlg.SetUrl( url );

            if ( dlg.ShowDialog( this ) == DialogResult.OK ) {
                this.Cursor = Cursors.WaitCursor;
                try {
                    feed = new Feed( dlg.Url, Properties.Settings.Default.ArticlesToFetch,m_ScriptingEvents);
                    m_FeedManager.Add( feed );
                    added = true;
                    m_ScriptingEvents.RaiseOnAddFeed( feed );
                } catch ( Exception e ) {
                    string message = e.Message;
                    string details = e.StackTrace;

                    new MyMessageBoxError( message, details ).ShowDialog( this );
                }
            }

            dlg.Dispose();

            if ( added ) {
                RefreshFeedDisplay( true, feed );
            }

            this.Cursor = Cursors.Default;
        }

        public void RemoveOneFeed( string title) {
            Feed feed = m_FeedManager.GetFeedByTitle( title );
            bool IsCustomFeed = feed.IsCustomSearchFeed;

            if ( TreeViewHelper.ReadNodesHidden.ContainsKey( feed.Url ) )
                TreeViewHelper.ReadNodesHidden.Remove( feed.Url );

            m_FeedManager.Remove( feed );
            FeedTree.Nodes.Remove( FeedTree.SelectedNode );

            //If user is removing custom feed, we do not want to remove articles on the original feeds.
            //otherwise if user is removing original feed, do find all the mathing custom feed article nodes and remove them too
            if ( !IsCustomFeed ) {
                List<TreeNode> ToBeRemovedNodes = new List<TreeNode>();

                foreach ( TreeNode roots in FeedTree.Nodes ) {
                    foreach ( TreeNode node in roots.Nodes ) {
                        if ( node.Level != 0 && node.Name != "fav" ) {
                            foreach ( FeedItem item in feed.Items ) {
                                if ( item.Url.Equals( node.Name ) )
                                    ToBeRemovedNodes.Add( node );
                            }
                        }
                    }
                }

                foreach ( TreeNode n in ToBeRemovedNodes ) {
                    FeedTree.Nodes.Remove( n );
                }
            }

            if ( FeedTree.Nodes.Count > 0 )
                FeedTree.SelectedNode = FeedTree.Nodes[0];

            DisableButtonsAndMenus();
            UpdateStatusbar( false );
            m_ScriptingEvents.RaiseOnRemoveFeed( feed );
        }

        private void RemoveFeed() {
            if ( FeedTree.SelectedNode != null ) {
                if ( FeedTree.SelectedNode.Name != "fav" && FeedTree.SelectedNode.Level == 0 ) {
                    string title = FeedTree.SelectedNode.Name;
                    if ( m_RegistryManager.ShowRemoveFeedConfirmation ) {
                        if ( new MyMessageBoxAsk
                            ( "Do you want to remove " + "\"" + title + "\"?", m_RegistryManager, true ).
                            ShowDialog( this ) == DialogResult.Yes ) {
                            RemoveOneFeed( title);
                        }
                    } else {
                        RemoveOneFeed( title);
                    }
                }
            }
        }

        ScriptingEvents IMainWindowClient.Events {
            get { return m_ScriptingEvents; }
        }

        private void RefreshFeed( int max ) {
            try {
                if ( !m_SearchActive ) {
                    this.Cursor = Cursors.WaitCursor;
                    int LastSelectedIndex = FeedTree.SelectedNode.Index;
                    Feed feed = m_FeedManager.GetFeedByTitle( FeedTree.SelectedNode.Name );
                    string temp = statusBarPanelLeft.Text;
                    statusBarPanelLeft.Text = "Syncing feed from " + feed.Title;
                    if ( !feed.IsCustomSearchFeed ) {
                        feed.RefreshOrCreate( null, feed.Url, max,m_ScriptingEvents );
                    } else {
                        List<string> urls = new List<string>();
                        foreach ( Feed f in m_FeedManager.Feeds ) {
                            if ( !f.IsCustomSearchFeed )
                                urls.Add( f.Url );
                        }

                        feed.RefreshOrCreate( urls, feed.Url, max,m_ScriptingEvents );
                    }
                    statusBarPanelLeft.Text = temp;
                    RefreshFeedDisplay();
                    FeedTree.Focus();
                    FeedTree.SelectedNode = FeedTree.Nodes[LastSelectedIndex];
                    toolBarButtonRefresh.Enabled = true;
                    toolBarButtonRemove.Enabled = true;
                    this.Cursor = Cursors.Default;
                }
            } catch ( Exception ex ) {
                new MyMessageBoxError( ex.Message, ex.StackTrace ).ShowDialog( this );
            }
        }

        private void UpdateStatusbar( bool PossibleInternetConnectivityProblem ) {
            if ( !PossibleInternetConnectivityProblem ) {
                m_FeedCount = m_FeedManager.FeedCount;
                statusBarPanelLeft.Text = "Subscribed feeds: " + m_FeedCount.ToString();
            } else {
                statusBarPanelLeft.Text = "Failed to update some feeds. Connection issue.";
            }
        }

        private void RefreshFeedDisplay( bool IsFeedBeingAdded = false, Feed FeedBeingAdded = null ) {
            if ( !m_FormClosing ) {
                FeedTree.BeginUpdate();
                FeedTree.Nodes.Clear();
                InitFavoriteNodes();
                bool PossibleInternetConnectivityProblem = false;
                foreach ( Feed feed in m_FeedManager.Feeds ) {
                    TreeNode root = new TreeNode();
                    root.ToolTipText = feed.Description;
                    root.NodeFont = new Font( FeedTree.Font, FontStyle.Bold );

                    root.Name = feed.Title;

                    foreach ( FeedItem item in feed.Items ) {
                        TreeNode node = new TreeNode( item.Title );
                        node.ToolTipText = "Article published: " + item.Published;
                        node.Name = item.Url;

                        if ( m_FeedManager.VisitedItems.ContainsKey( item.Url ) )
                            node.ForeColor = Color.BlueViolet;
                        else
                            node.ForeColor = Color.Blue;

                        if ( !m_FeedManager.RemovedItems.Contains( item.Url ) )
                            root.Nodes.Add( node );
                    }

                    //Append some extra space for the bold font...sigh.
                    //In case of timeout, the title might be empty...
                    if ( feed.Title != null ) {
                        root.Text = feed.Title + "                    ";
                        feed.DoNotLoad = false;
                        FeedTree.Nodes.Add( root );
                    } else {
                        //check if feed do not load is true already.
                        //if it is, set picp to false
                        //that way, the error goes away. no need to display it multiple times
                        if ( feed.DoNotLoad ) {
                            PossibleInternetConnectivityProblem = false;
                        } else {
                            PossibleInternetConnectivityProblem = true;

                            //mark it as toberemoved so it won't get loaded anymore
                            feed.DoNotLoad = true;
                        }
                    }
                }

                m_CanModifyRuntimeExpansionMemoryList = false;

                if ( !IsFeedBeingAdded ) {
                    foreach ( string title in m_RuntimeExpansionMemoryList ) {
                        if ( FeedTree.Nodes.ContainsKey( title ) ) {
                            if ( !FeedTree.Nodes[title].IsExpanded )
                                FeedTree.Nodes[title].Expand();
                            else
                                FeedTree.Nodes[title].Collapse();
                        }
                    }
                } else {
                    if ( FeedBeingAdded != null ) {
                        FeedTree.SelectedNode = TreeViewHelper.GetRootTreeNodeByTitle( FeedTree, FeedBeingAdded.Title );
                        if ( FeedTree.SelectedNode != null )
                            FeedTree.SelectedNode.Expand();
                    }
                }

                m_CanModifyRuntimeExpansionMemoryList = true;

                if ( toolBarButtonAsRead.Pushed )
                    HideReadItems();

                FeedTree.EndUpdate();
                UpdateStatusbar( PossibleInternetConnectivityProblem );
                DisableButtonsAndMenus();
            }
        }

        private void FeedTree_NodeMouseClick( object sender, TreeNodeMouseClickEventArgs e ) {
            if ( e.Button == MouseButtons.Right ) {
                FeedTree.SelectedNode = e.Node;
            }
            //Let's check that we clicked a root node
            if ( e.Node.Level == 0 && e.Node.Name != "fav" ) {
                toolBarButtonRefresh.Enabled = true;
                toolBarButtonRemove.Enabled = true;
            } else {
                DisableButtonsAndMenus();
            }

            FavoriteItem item = m_FeedManager.GetFavoriteByUrl( e.Node.Name );

            if ( item != null ) {
                if ( m_FeedManager.StarredItems.Contains( item ) )
                    toolBarButtonStar.Enabled = false;
                else
                    if ( e.Node.Level != 0 )
                        toolBarButtonStar.Enabled = true;
            } else {
                if ( e.Node.Level != 0 && e.Node.Name != "fav" ) {
                    toolBarButtonStar.Enabled = true;
                }
            }

            if ( textBoxSearch.Text == "" ) {
                m_CanSearch = false;
                textBoxSearch.ForeColor = Color.Gray;
                textBoxSearch.Text = "Type to search";
                m_CanSearch = true;

                ClearSearch();
            }

            if ( e.Node.Name != "fav" && e.Node.Level != 0 ) {
                toolBarButtonCopyUrl.Enabled = true;
                toolBarButtonOpenBrowser.Enabled = true;
            } else {
                toolBarButtonCopyUrl.Enabled = false;
                toolBarButtonOpenBrowser.Enabled = false;
            }

        }

        private void FeedTree_NodeMouseDoubleClick( object sender, TreeNodeMouseClickEventArgs e ) {
            OpenInBrowser();
        }

        private void menuItemAdd_Click( object sender, EventArgs e ) {
            AddFeed();
        }

        private void menuItemRemove_Click( object sender, EventArgs e ) {
            RemoveFeed();
        }

        private void menuItemRefresh_Click( object sender, EventArgs e ) {
            RefreshFeed( Properties.Settings.Default.ArticlesToFetch );
        }

        private void menuItemHideRead_Click( object sender, EventArgs e ) {
            if ( menuItemHideRead.Checked ) {
                ShowReadItems();
                menuItemHideRead.Checked = false;
                Properties.Settings.Default.HideReadItems = false;
                toolBarButtonAsRead.Pushed = false;
            } else {
                HideReadItems();
                menuItemHideRead.Checked = true;
                Properties.Settings.Default.HideReadItems = true;
                toolBarButtonAsRead.Pushed = true;
            }
        }

        private void MenuItemFeed_Popup( object sender, EventArgs e ) {

            menuItemHostOnWebServer.Enabled = false;
            
            if ( FeedTree.SelectedNode != null ) {
                if ( FeedTree.SelectedNode.Level == 0 ) {
                    menuItemRefresh.Enabled = true;
                    if ( FeedTree.SelectedNode.Name != "fav" ) {
                        menuItemRemove.Enabled = true;
                        menuItemRefresh.Enabled = true;
                        menuItemFetchFeed.Enabled = true;

                        if ( !m_FeedManager.GetFeedByTitle( FeedTree.SelectedNode.Name ).WebServerRunning ) {
                            menuItemHostOnWebServer.Enabled = true;
                            menuItemHostOnWebServer.Text = "Start Hosting This Feed";
                        } else if ( m_FeedManager.GetFeedByTitle( FeedTree.SelectedNode.Name ).WebServerRunning ) {
                            menuItemHostOnWebServer.Enabled = true;
                            menuItemHostOnWebServer.Text = "Stop Hosting This Feed";
                        }

                    } else {
                        menuItemRemove.Enabled = false;
                        menuItemRefresh.Enabled = false;
                        menuItemFetchFeed.Enabled = false;
                    }
                } else {
                    DisableButtonsAndMenus();
                }
            } else
                DisableButtonsAndMenus();

            menuItemHideRead.Checked = Properties.Settings.Default.HideReadItems;

            if ( m_SearchActive )
                menuItemCreateFeedFromSearch.Enabled = true;
            else
                menuItemCreateFeedFromSearch.Enabled = false;
        }

        private void menuItemExit_Click( object sender, EventArgs e ) {
            this.Close();
        }

        private void menuItemExportAsXml_Click( object sender, EventArgs e ) {
            ExportFeedsXmlDialog dlg = new ExportFeedsXmlDialog( m_FeedManager );

            if ( dlg.ShowDialog( this ) == DialogResult.OK ) {
                string path = dlg.SelectedPath;
                this.Cursor = Cursors.WaitCursor;

                try {
                    m_FeedManager.PreserveFeeds( path );
                } catch ( Exception ex ) {
                    new MyMessageBoxError( ex.Message, ex.StackTrace ).ShowDialog( this );
                }

                this.Cursor = Cursors.Default;
            }
        }

        private void OnShownInit() {
            //Read stored state       
            new FirstTimeInstall( m_RegistryManager ).MarkAsInstalled();

            m_FeedManager = FeedManager.Load( this,m_Path, m_RegistryManager, m_ScriptingEvents);
            
            ScriptingMethods.m_FeedManager = this.m_FeedManager;
            ScriptingMethods.m_View = this.FeedTree;
            ScriptingMethods.m_Menu = this.mainMenu1;
            ScriptingMethods.m_Events = this.m_ScriptingEvents;
            ScriptingMethods.m_Client = this;

            m_FeedManager.ReloadRemovedItems( m_Path );
            RefreshFeedDisplay();

            if ( Properties.Settings.Default.HideReadItems ) {
                HideReadItems();
                toolBarButtonAsRead.Pushed = true;
            }

            List<string> nodes = m_TreeState.LoadState();

            foreach ( string name in nodes ) {
                foreach ( TreeNode node in FeedTree.Nodes ) {
                    if ( node.Name.Equals( name ) )
                        node.Expand();
                }
            }

            if ( m_OnLaunchAddUrl != null ) {
                AddFeed( m_OnLaunchAddUrl );
            }

            m_Timer.Start();

            if ( m_RegistryManager.ShowRecommendedFeedsOnStartUp ) {
                RecommendedFeedsDialog dlg = new RecommendedFeedsDialog( new Point( this.Location.X + ( this.Width - 437 ) / 2,
                                                                      this.Location.Y + ( this.Height - 421 ) / 2 ), this
                                                                      );
                if ( dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK ) {

                }
            }

            m_ScriptManager = new ScriptManager(m_ScriptingEvents);

            if ( Properties.Settings.Default.ActivateScripts ) {
                foreach ( Script s in m_ScriptManager.Scripts ) {
                    if ( s.Enabled ) {
                        m_ScriptManager.Instantiate( s );
                    }
                }
            }

            if ( Properties.Settings.Default.RefreshFeedsOnStartup )
                new Thread( SyncAllFeeds ).Start();

            if ( Properties.Settings.Default.CheckForUpdates ) {
                if ( UpdateManager.CheckForUpdate( Application.ProductVersion ) ) {
                    if ( new MyMessageBoxAsk( "News Worm software update is available. Download and install it?" ).ShowDialog() == DialogResult.Yes ) {
                        statusBarPanelRight.Text = "Downloading software update, please wait...";
                        this.Cursor = Cursors.WaitCursor;
                        UpdateManager.DownloadAndInstallUpdate( this );
                        this.Cursor = Cursors.Default;
                    }
                }
            }
        }

        public void AppClose() {
            this.Close();
        }

        private void MainWindow_Shown( object sender, EventArgs e ) {
            //check for a valid licence
          
            OnShownInit();
         
        }

        private void SaveSettingsAndFeeds() {
            if ( !m_NoLicenceUserCancel ) {
                m_FeedManager.PreserveState( m_Path );
                m_FeedManager.SaveUrlHistory( m_Path );
                m_FeedManager.SaveFavoriteHistory( m_Path );
                m_FeedManager.SaveExportPaths( m_Path );

                m_TreeState.Save( FeedTree );

                m_Timer.Stop();
            }
        }

        private void MainWindow_FormClosing( object sender, FormClosingEventArgs e ) {
            if ( !m_IsSyncOnGoing && !m_IsCustomFeedSyncOnGoing) {
                m_FormClosing = true;
                SaveSettingsAndFeeds();
            } else {
                new ClosingConnectionsDialog( new Point( this.Location.X + ( this.Width - 354 ) / 2,
                                                 this.Location.Y + ( this.Height - 421 ) / 2 ) ).Show();
                while ( m_IsSyncOnGoing || m_IsCustomFeedSyncOnGoing ) {
                    Application.DoEvents();
                    if ( !m_IsSyncOnGoing && !m_IsCustomFeedSyncOnGoing) {
                        m_FormClosing = true;
                        SaveSettingsAndFeeds();
                    }
                }
            }
        }

        private void menuItemFile_Popup( object sender, EventArgs e ) {
            if ( m_FeedManager.Feeds.Count > 0 )
                menuItemExportAsXml.Enabled = true;
            else
                menuItemExportAsXml.Enabled = false;
        }

        private void ContextMenuItems_Popup( object sender, EventArgs e ) {
            ContextMenuItems.MenuItems.Clear();

            if ( FeedTree.SelectedNode != null ) {
                if ( FeedTree.SelectedNode.Level != 0 ) {
                    ContextMenuItems.MenuItems.Add( "&Open In Browser...",
                         new EventHandler( this.ContextMenuItemOpenInBrowser_OnClick ) );

                    ContextMenuItems.MenuItems.Add( "&Mark As Read",
                        new EventHandler( this.ContextMenuItemMarkAsRead_OnClick ) );

                    ContextMenuItems.MenuItems.Add( "&Email Url",
                        new EventHandler( this.ContextMenuItemSendViaEmail_OnClick ) );

                    ContextMenuItems.MenuItems.Add( "&Copy Url",
                        new EventHandler( this.ContextMenuItemCopyLink_OnClick ) );

                    ContextMenuItems.MenuItems.Add( "&Mark As Favorite",
                        new EventHandler( this.ContextMenuItemMarkAsFavorite_OnClick ) );

                    ContextMenuItems.MenuItems.Add( "&Remove Favorite",
                        new EventHandler( this.ContextMenuItemRemoveFavorite_OnClick ) );

                    ContextMenuItems.MenuItems[0].DefaultItem = true;

                    //Mark "mark as read" disabled if current article is already read
                    if ( m_FeedManager.VisitedItems.ContainsKey( FeedTree.SelectedNode.Name ) || FeedTree.SelectedNode.Parent.Name == "fav" )
                        ContextMenuItems.MenuItems[1].Enabled = false;
                    else
                        ContextMenuItems.MenuItems[1].Enabled = true;

                    FavoriteItem favItem = m_FeedManager.GetFavoriteByUrl( FeedTree.SelectedNode.Name );
                    if ( favItem != null ) {
                        if ( m_FeedManager.StarredItems.Contains( favItem ) ) {
                            foreach ( MenuItem item in ContextMenuItems.MenuItems ) {
                                if ( item.Text == "&Mark As Favorite" ) {
                                    item.Enabled = false;
                                }
                            }
                        }
                    }

                    FavoriteItem favorite = m_FeedManager.GetFavoriteByUrl( FeedTree.SelectedNode.Name );
                    if ( favorite != null ) {
                        foreach ( MenuItem item in ContextMenuItems.MenuItems ) {
                            if ( item.Text == "&Remove Favorite" ) {
                                item.Enabled = true;
                            }
                        }
                    } else {
                        foreach ( MenuItem item in ContextMenuItems.MenuItems ) {
                            if ( item.Text == "&Remove Favorite" ) {
                                item.Enabled = false;
                            }
                        }
                    }
                } //FeedTree.SelectedNode.Level != 0
                else {
                    if ( FeedTree.SelectedNode.Name != "fav" ) {

                        ContextMenuItems.MenuItems.Add( "&Fetch...",
                           new EventHandler( this.ContextMenuItemFetchFeed_OnClick ) );

                        ContextMenuItems.MenuItems.Add( "&Refresh",
                           new EventHandler( this.ContextMenuItemRefreshFeed_OnClick ) );

                        ContextMenuItems.MenuItems.Add( "&Remove...",
                            new EventHandler( this.ContextMenuItemRemoveFeed_OnClick ) );

                        if ( !IsFeedHosted( FeedTree.SelectedNode ) ) {
                            ContextMenuItems.MenuItems.Add( "&Start Hosting This Feed",
                                new EventHandler( this.ContextMenuItemHostFeedOnWebServer_OnClick ) );
                        } else if ( IsFeedHosted( FeedTree.SelectedNode ) ) {
                            ContextMenuItems.MenuItems.Add( "&Stop Hosting This Feed",
                               new EventHandler( this.ContextMenuItemHostFeedOnWebServer_OnClick ) );
                        }

                        ContextMenuItems.MenuItems[0].DefaultItem = true;
                    }
                }
            }
        }

        private bool IsFeedHosted( TreeNode node ) {

            Feed f = m_FeedManager.GetFeedByTitle( node.Name );

            if ( f != null ) {
                if ( f.WebServerRunning ) {
                    return true;
                }
            }

            return false;
        }

        private void RemoveFavorite() {
            if ( FeedTree.SelectedNode != null ) {
                FavoriteItem item = m_FeedManager.GetFavoriteByUrl( FeedTree.SelectedNode.Name ) ;
                m_FeedManager.StarredItems.Remove
                    ( m_FeedManager.GetFavoriteByUrl( FeedTree.SelectedNode.Name ) );

                FeedTree.Nodes.Remove( FeedTree.SelectedNode );
                m_ScriptingEvents.RaiseOnRemoveFavorite( item );
            }
        }

        private void SendViaEmail() {
            try {
                if ( FeedTree.SelectedNode != null ) {
                    string subject = "Article via News Worm: " +
                        m_FeedManager.GetFeedItemByUrl( FeedTree.SelectedNode.Name ).Title + " (" +
                        FeedTree.SelectedNode.Parent.Name + ")";

                    string body = FeedTree.SelectedNode.Name;

                    Process.Start( "mailto:?subject=" + subject + "&body=" + body );
                }
            } catch ( Exception ex ) {
                new MyMessageBoxError( ex.Message, ex.StackTrace ).ShowDialog( this );
            }
        }

        void IMainWindowClient.MarkArticleAsRead( string url ) {
            if ( !m_FeedManager.VisitedItems.ContainsKey( url ) ) {
                FeedItem article = m_FeedManager.GetFeedItemByUrl( url );
                m_FeedManager.VisitedItems.Add( article.ArticleUrl, article.ArticleTitle );
                TreeNode[] nodes = FeedTree.Nodes.Find( article.ArticleUrl, true );
                foreach ( TreeNode node in nodes ) {
                    node.ForeColor = Color.BlueViolet;
                    if ( Properties.Settings.Default.HideReadItems ) {
                        TreeViewHelper.AddNodeToReadNodes( node.Parent.Name, node, node.Index );
                        FeedTree.Nodes.Remove( node );
                    }
                }
                m_ScriptingEvents.RaiseOnMarkAsRead( article );
            }
        }

        private void MarkAsRead() {
            if ( FeedTree.SelectedNode != null ) {
                if ( FeedTree.SelectedNode.Level != 0 ) {
                    if ( FeedTree.SelectedNode.Name != "fav" ) {
                        if ( !m_FeedManager.VisitedItems.ContainsKey( FeedTree.SelectedNode.Name ) ) {
                            FeedItem item = m_FeedManager.GetFeedItemByUrl( FeedTree.SelectedNode.Name );
                            m_FeedManager.VisitedItems.Add( item.Url, item.Title );
                            TreeNode[] nodes = FeedTree.Nodes.Find( item.Url, true );
                            foreach ( TreeNode node in nodes ) {
                                node.ForeColor = Color.BlueViolet;
                                if ( Properties.Settings.Default.HideReadItems ) {
                                    TreeViewHelper.AddNodeToReadNodes( node.Parent.Name, node, node.Index );
                                    FeedTree.Nodes.Remove( node );
                                }
                            }
                            m_ScriptingEvents.RaiseOnMarkAsRead( item );
                        }
                    }
                }
            }
        }

        private void MarkAsRead( TreeNode node ) {
            if ( node != null ) {
                if ( node.Name != "fav" && node.Level != 0 ) {
                    if ( !m_FeedManager.VisitedItems.ContainsKey( node.Name ) ) {
                        FeedItem item = m_FeedManager.GetFeedItemByUrl( node.Name );
                        m_FeedManager.VisitedItems.Add( item.Url, item.Title );
                        TreeNode[] nodes = FeedTree.Nodes.Find( item.Url, true );
                        foreach ( TreeNode n in nodes ) {
                            n.ForeColor = Color.BlueViolet;
                            if ( Properties.Settings.Default.HideReadItems ) {
                                TreeViewHelper.AddNodeToReadNodes( n.Parent.Name, n, n.Index );
                                FeedTree.Nodes.Remove( n );
                            }
                        }
                        m_ScriptingEvents.RaiseOnMarkAsRead( item );
                    }
                }
            }
        }

        private void OpenInBrowser() {
            if ( FeedTree.SelectedNode != null ) {
                if ( FeedTree.SelectedNode.Level != 0 ) {
                    try {
                        string url = FeedTree.SelectedNode.Name;
                        MarkAsRead();
                        System.Diagnostics.Process.Start( url );
                    } catch ( Exception ex ) {
                        new MyMessageBoxError( ex.Message, ex.StackTrace ).ShowDialog( this );
                    }
                }
            }
        }

        private void CopyLink() {
            if ( FeedTree.SelectedNode != null ) {
                if ( FeedTree.SelectedNode.Level != 0 ) {
                    this.Cursor = Cursors.WaitCursor;
                    string tmp = this.statusBarPanelLeft.Text;
                    this.statusBarPanelLeft.Text = "Creating short url...";
                    Clipboard.SetText( UrlShortener.Shorten( FeedTree.SelectedNode.Name ) );
                    this.statusBarPanelLeft.Text = tmp;
                    this.Cursor = Cursors.Default;
                }
            }
        }

        void IMainWindowClient.MarkAsFavorite( string url ) {
            if ( !m_FeedManager.StarredItems.Contains( m_FeedManager.GetFavoriteByUrl( url ) ) ) {

                TreeNode FavoriteRootNode = null;

                if ( !m_SearchActive ) {
                    foreach ( TreeNode node in FeedTree.Nodes ) {
                        if ( node.Text.Equals( "Favorites         " ) ) {
                            FavoriteRootNode = node;
                            break;
                        }
                    }
                } else {
                    foreach ( TreeNode node in m_SearchManager.OldNodes ) {
                        if ( node.Text.Equals( "Favorites         " ) ) {
                            FavoriteRootNode = node;
                            break;
                        }
                    }
                }

                if ( FavoriteRootNode != null ) {
                    FeedItem article = m_FeedManager.GetFeedItemByUrl( url );
                    FavoriteItem favorite = new FavoriteItem( article.ArticleUrl, article.ArticleTitle, article.ArticleSummary );
                    m_FeedManager.StarredItems.Add( favorite );
                    TreeNode FavoriteNode = new TreeNode();
                    FavoriteNode.Name = article.ArticleUrl;
                    FavoriteNode.Text = article.ArticleTitle;

                    FavoriteRootNode.Nodes.Add( FavoriteNode );
                    toolBarButtonStar.Enabled = false;
                    m_ScriptingEvents.RaiseOnAddFavorite( favorite );
                }
            }
        }

        private void MarkAsFavorite() {
            if ( FeedTree.SelectedNode != null ) {
                if ( FeedTree.SelectedNode.Level != 0 ) {
                    string url = FeedTree.SelectedNode.Name;
                    TreeNode favoriteNode = null;

                    if ( !m_SearchActive ) {
                        foreach ( TreeNode node in FeedTree.Nodes ) {
                            if ( node.Text.Equals( "Favorites         " ) ) {
                                favoriteNode = node;
                                break;
                            }
                        }
                    } else {
                        foreach ( TreeNode node in m_SearchManager.OldNodes ) {
                            if ( node.Text.Equals( "Favorites         " ) ) {
                                favoriteNode = node;
                                break;
                            }
                        }
                    }

                    if ( favoriteNode != null ) {
                        //If we have the item,  Let's not add it again.
                        if ( !m_FeedManager.StarredItems.Contains( m_FeedManager.GetFavoriteByUrl( url ) ) ) {
                            FeedItem item = m_FeedManager.GetFeedItemByUrl( url );
                            FavoriteItem FavItem = new FavoriteItem( item.Url, item.Title, item.Summary );
                            m_FeedManager.StarredItems.Add( FavItem );
                            TreeNode subNode = new TreeNode();
                            subNode.Name = url;
                            subNode.Text = m_FeedManager.GetFeedItemByUrl( url ).Title;
                            favoriteNode.Nodes.Add( subNode );
                            toolBarButtonStar.Enabled = false;
                            m_ScriptingEvents.RaiseOnAddFavorite( FavItem );
                        }
                    }
                }
            }
        }

        private void SetFetchCount() {
            if ( FeedTree.SelectedNode != null ) {
                Feed feed = m_FeedManager.GetFeedByTitle( FeedTree.SelectedNode.Name.Trim() );
                FetchArticlesCountDialog dlg = new FetchArticlesCountDialog( feed, m_Path );

                if ( dlg.ShowDialog() == DialogResult.OK ) {
                    RefreshFeed( dlg.OverrideCount );
                }
            }
        }

        protected void ContextMenuItemFetchFeed_OnClick( Object sender, EventArgs e ) {
            SetFetchCount();
        }

        protected void ContextMenuItemRemoveFeed_OnClick( Object sender, EventArgs e ) {
            RemoveFeed();
        }

        protected void ContextMenuItemRefreshFeed_OnClick( Object sender, EventArgs e ) {
            RefreshFeed( Properties.Settings.Default.ArticlesToFetch );
        }

        protected void ContextMenuItemHostFeedOnWebServer_OnClick( Object sender, EventArgs e ) {
            StartStopWebServerForFeed( FeedTree.SelectedNode );
        }

        protected void ContextMenuItemMarkAsFavorite_OnClick( Object sender, EventArgs e ) {
            MarkAsFavorite();
        }

        protected void ContextMenuItemRemoveFavorite_OnClick( Object sender, EventArgs e ) {
            RemoveFavorite();
        }

        protected void ContextMenuItemCopyLink_OnClick( Object sender, EventArgs e ) {
            CopyLink();
        }

        protected void ContextMenuItemOpenInBrowser_OnClick( Object sender, EventArgs e ) {
            OpenInBrowser();
        }

        protected void ContextMenuItemSendViaEmail_OnClick( Object sender, EventArgs e ) {
            SendViaEmail();
        }

        protected void ContextMenuItemMarkAsRead_OnClick( Object sender, EventArgs e ) {
            MarkAsRead();
        }

        private void menuItemAbout_Click( object sender, EventArgs e ) {
            new AboutDialog().ShowDialog();
        }

        private void menuItemEmailLink_Click( object sender, EventArgs e ) {
            SendViaEmail();
        }

        private void menuItemMarkAsRead_Click( object sender, EventArgs e ) {
            MarkAsRead();
        }

        private void menuItemItems_Popup( object sender, EventArgs e ) {

            if ( FeedTree.SelectedNode != null && FeedTree.SelectedNode.Level != 0 ) {
                menuItemMarkAsRead.Enabled = true;
                menuItemEmailLink.Enabled = true;
                menuItemOpenInBrowser.Enabled = true;
                menuItemCopyLink.Enabled = true;

                if ( m_FeedManager.StarredItems.Contains(
                    m_FeedManager.GetFavoriteByUrl( FeedTree.SelectedNode.Name ) ) ) {
                    menuItemMarkAsFavorite.Enabled = false;
                    menuItemRemoveFavorite.Enabled = true;

                } else {
                    menuItemMarkAsFavorite.Enabled = true;
                    menuItemRemoveFavorite.Enabled = false;
                }

                if ( m_FeedManager.VisitedItems.ContainsKey( FeedTree.SelectedNode.Name ) )
                    menuItemMarkAsRead.Enabled = false;

            } else {
                menuItemMarkAsRead.Enabled = false;
                menuItemEmailLink.Enabled = false;
                menuItemOpenInBrowser.Enabled = false;
                menuItemCopyLink.Enabled = false;
                menuItemMarkAsFavorite.Enabled = false;
                menuItemRemoveFavorite.Enabled = false;
            }


        }

        private void MainWindow_Resize( object sender, EventArgs e ) {
            FeedTree.Size = new Size( FeedTree.Width, this.ClientSize.Height - 52 );

            if ( WindowState == FormWindowState.Minimized ) {
                if ( Properties.Settings.Default.MinimizeToTray ) {
                    this.ShowInTaskbar = false;

                }
            }
        }

        private List<TreeNode> m_TemporaryReadNodes = new List<TreeNode>();

        private void textBoxSearch_TextChanged( object sender, EventArgs e ) {
            if ( m_CanSearch ) {
                m_SearchActive = true;
                FeedTree.BeginUpdate();
                m_Timer.Stop();
                m_TemporaryReadNodes.Clear();

                m_SearchManager.SetBackupNodes( FeedTree.Nodes );

                if ( Properties.Settings.Default.HideReadItems ) {

                    foreach ( KeyValuePair<string, Dictionary<TreeNode, int>> kvp in TreeViewHelper.ReadNodesHidden ) {
                        foreach ( KeyValuePair<TreeNode, int> k in kvp.Value ) {

                            string key = kvp.Key;
                            int index = k.Value;
                            TreeNode value = k.Key;
                            TreeNode parent = null;
                            TreeNode[] results = FeedTree.Nodes.Find( key, true );

                            if ( results.Length > 0 ) {
                                parent = results[0];

                                if ( parent.Nodes.Count < index )
                                    index = parent.Nodes.Count;

                                parent.Nodes.Insert( index, value );
                                m_TemporaryReadNodes.Add( parent );
                            }
                        }
                    }
                    m_SearchManager.SetBackupReadNodes( m_TemporaryReadNodes );
                }

                FeedTree.Nodes.Clear();

                List<TreeNode> Results = m_SearchManager.PerformSearch( this.textBoxSearch.Text,
                    m_FeedManager.Feeds, FeedTree.Font, m_FeedManager );

                foreach ( TreeNode root in Results ) {
                    if ( !FeedTree.Nodes.Contains( root ) )
                        this.FeedTree.Nodes.Add( root );
                }

                if ( FeedTree.Nodes.Count > 0 ) {
                    toolBarButtonCreateFromSearch.Enabled = true;
                    toolBarButtonRemove.Enabled = true;
                    toolBarButtonRefresh.Enabled = true;
                    foreach ( TreeNode node in FeedTree.Nodes )
                        node.Expand();
                } else {
                    toolBarButtonCreateFromSearch.Enabled = false;
                    toolBarButtonRemove.Enabled = false;
                    toolBarButtonRefresh.Enabled = false;
                }

                if ( Properties.Settings.Default.HideReadItems )
                    HideReadItems();

                FeedTree.EndUpdate();
            }
        }

        private void MouseClickOnSearchBox() {
            if ( textBoxSearch.Text == "Type to search" ) {
                m_CanSearch = false;
                textBoxSearch.Text = "";
                textBoxSearch.ForeColor = Color.Black;
                m_CanSearch = true;
            }
        }

        private void textBoxSearch_MouseClick( object sender, MouseEventArgs e ) {
            MouseClickOnSearchBox();
        }

        private void menuItemOpenInBrowser_Click( object sender, EventArgs e ) {
            OpenInBrowser();
        }

        private void menuItemCopyLink_Click( object sender, EventArgs e ) {
            CopyLink();
        }

        private void menuItemMarkAsFavorite_Click( object sender, EventArgs e ) {
            MarkAsFavorite();
        }

        private void SaveProperties() {

            if ( Properties.Settings.Default.SaveWindowPosition ) {
                if ( this.WindowState != FormWindowState.Minimized ) {
                    Properties.Settings.Default.LocationX = this.Left;
                    Properties.Settings.Default.LocationY = this.Top;
                    Properties.Settings.Default.WindowWidth = this.Width;
                    Properties.Settings.Default.WindowHeight = this.Height;
                }
            }

            Properties.Settings.Default.Save();
        }

        private void MainWindow_FormClosed( object sender, FormClosedEventArgs e ) {
            SaveProperties();
        }

        private void MainWindow_Load( object sender, EventArgs e ) {
            this.Left = (int)Properties.Settings.Default.LocationX;
            this.Top = (int)Properties.Settings.Default.LocationY;
            this.Width = (int)Properties.Settings.Default.WindowWidth;
            this.Height = (int)Properties.Settings.Default.WindowHeight;
        }

        private void FeedTree_AfterExpand( object sender, TreeViewEventArgs e ) {
            if ( m_CanModifyRuntimeExpansionMemoryList ) {
                if ( !m_SearchActive ) {
                    if ( !m_RuntimeExpansionMemoryList.Contains( e.Node.Name ) )
                        m_RuntimeExpansionMemoryList.Add( e.Node.Name );
                }
            }
            FeedTree.SelectedNode = e.Node;
        }

        private void FeedTree_AfterCollapse( object sender, TreeViewEventArgs e ) {
            if ( m_CanModifyRuntimeExpansionMemoryList ) {
                if ( !m_SearchActive ) {
                    if ( m_RuntimeExpansionMemoryList.Contains( e.Node.Name ) )
                        m_RuntimeExpansionMemoryList.Remove( e.Node.Name );
                }
            }
            FeedTree.SelectedNode = e.Node;
        }

        private void menuItemRemoveFavorite_Click( object sender, EventArgs e ) {
            RemoveFavorite();
        }

        private void menuItemProperties_Click( object sender, EventArgs e ) {
            PreferencesDialog dlg = new PreferencesDialog( m_RegistryManager, m_FeedManager.Feeds , m_FeedManager);

            if ( dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK ) {
                m_Timer.Interval = GetCurrentMilliSecondsFromSettings();
                if ( Properties.Settings.Default.MinimizeToTray || Properties.Settings.Default.NewArticleNotification )
                    notifyIconNewsWorm.Visible = true;
                else
                    notifyIconNewsWorm.Visible = false;

                //Should we have this? Propably not, ask user to restart News Worm instead....
              /*  if ( Properties.Settings.Default.ActivateScripts ) {
                    foreach ( Script s in m_ScriptManager.Scripts )
                        if(s.Enabled)
                            m_ScriptManager.Instantiate( s );
                }*/
            }
        }

        private void menuItemFetchFeed_Click( object sender, EventArgs e ) {
            SetFetchCount();
        }

        private void HandleTreeViewSelection( TreeNode Node ) {
            if ( Node.Level == 0 ) {
                toolBarButtonStar.Enabled = false;
                toolBarButtonRefresh.Enabled = true;
                toolBarButtonRemove.Enabled = true;
                toolBarButtonOpenBrowser.Enabled = false;
                toolBarButtonCopyUrl.Enabled = false;
            }

            if ( Node.Name.Equals( "fav" ) ) {
                toolBarButtonRefresh.Enabled = false;
                toolBarButtonRemove.Enabled = false;
            }

            if ( Node.Level != 0 ) {
                //Handle arrow keys based selection
                toolBarButtonRefresh.Enabled = false;
                toolBarButtonRemove.Enabled = false;

                if ( Node.Parent.Name.Equals( "fav" ) )
                    toolBarButtonStar.Enabled = false;
                else {
                    FavoriteItem item = m_FeedManager.GetFavoriteByUrl( Node.Name );
                    if ( item == null )
                        toolBarButtonStar.Enabled = true;
                    else
                        toolBarButtonStar.Enabled = false;
                }

                toolBarButtonOpenBrowser.Enabled = true;
                toolBarButtonCopyUrl.Enabled = true;
            }
        }

        private void FeedTree_BeforeSelect( object sender, TreeViewCancelEventArgs e ) {
            HandleTreeViewSelection( e.Node );
        }

        private void menuItemRecommendedFeeds_Click( object sender, EventArgs e ) {
            new RecommendedFeedsDialog( new Point( this.Location.X + ( this.Width - 437 ) / 2,
                                                 this.Location.Y + ( this.Height - 421 ) / 2 ), this
                                                 ).ShowDialog();
        }


        void IMainWindowClient.AddRecommendedFeed( RecommendedFeed feed ) {
            Feed f = feed;
            m_FeedManager.Add( f );
        }

        void IMainWindowClient.DisableRecommendedFeedOnStartup() {
            m_RegistryManager.SetShowRecommendedFeedsOnStartUp( false );
        }

        void IMainWindowClient.EnableRecommendedFeedOnStartup() {
            m_RegistryManager.SetShowRecommendedFeedsOnStartUp( true );
        }

        void IMainWindowClient.RefreshAll() {
            RefreshFeedDisplay();
        }

        bool IMainWindowClient.ShowOnStartUp { get { return m_RegistryManager.ShowRecommendedFeedsOnStartUp; } }

        List<Feed> IMainWindowClient.AvailableFeeds {
            get { return m_FeedManager.Feeds; }
        }

        void IMainWindowClient.RemoveFeedIfAvailable( Feed feed ) {
            m_FeedManager.Remove( feed );
        }

        private void ActivateSearchBox() {
            if ( !m_SearchActive) {
                MouseClickOnSearchBox();
                textBoxSearch.Focus();
            }
        }

        private void MainWindow_KeyDown( object sender, KeyEventArgs e ) {
            if ( e.KeyCode == Keys.Delete ) {
                RemoveFeed();
            } else if ( e.KeyCode == Keys.F5 ) {
                Thread th = new Thread(SyncAllFeeds);
                th.Start();
            } else if ( e.KeyCode == Keys.Escape ) {
                if ( m_SearchActive ) {
                    ClearSearch();
                }
            } else if ( e.KeyCode == Keys.Space ) { //Also ctrl+r works
                MarkAsRead();
            } else if ( e.KeyCode == Keys.Enter ) { //Also ctrl+o
                OpenInBrowser();
            } else if ( e.KeyCode == Keys.F3 ) {
                ActivateSearchBox();
            }
        }

        private void menuItemScripting_Click( object sender, EventArgs e ) {
            new ScriptsDialog( ref m_ScriptManager,
                 new Point( this.Location.X + ( this.Width - 740 ) / 2,
                                                                      this.Location.Y + ( this.Height - 580 ) / 2 ) ).Show();
        }

        private void FeedTree_AfterSelect( object sender, TreeViewEventArgs e ) {
            this.statusBarPanelCenter.Text = "";
            if ( FeedTree.SelectedNode != null ) {
                if ( FeedTree.SelectedNode.Name != "fav" ) {
                    if ( FeedTree.SelectedNode.Level == 0 ) {
                        Feed feed = m_FeedManager.GetFeedByTitle( FeedTree.SelectedNode.Name );
                        if ( feed != null ) {
                            this.statusBarPanelCenter.Text = feed.GetUnreadArticleCount( m_FeedManager.VisitedItems ) + "/" +
                                feed.Items.Count;
                        }
                    }
                }
            }
        }

        private void menuItemRefreshAllFeeds_Click( object sender, EventArgs e ) {
            new Thread( SyncAllFeeds ).Start();
        }

        private void menuItemHomepage_Click( object sender, EventArgs e ) {
            try {
                Process.Start( "http://www.newsworm.net." );
            } catch ( Exception ex ) {
                Console.WriteLine( ex.Message );
            }
        }

        private void menuItemExpandAll_Click( object sender, EventArgs e ) {
            ExpandAll();
        }

        private void menuItemCollapseAll_Click( object sender, EventArgs e ) {
            CollapseAll();
        }

        private void menuItemCreateFeedFromSearch_Click( object sender, EventArgs e ) {
            this.Cursor = Cursors.WaitCursor;
            CreateFeedFromSearchResults();
            this.Cursor = Cursors.Default;
        }

        private void notifyIconNewsWorm_DoubleClick( object sender, EventArgs e ) {
            this.WindowState = m_LastWindowStateBeforeMinimize;
            this.ShowInTaskbar = true;
        }

        private void contextMenuTray_Popup( object sender, EventArgs e ) {
            contextMenuTray.MenuItems.Clear();
            contextMenuTray.MenuItems.Add( "&Exit",
                         new EventHandler( this.ContextMenuTrayItemExit_OnClick ) );
        }

        private void ContextMenuTrayItemExit_OnClick( object sender, EventArgs e ) {
            this.Close();
        }

        void IMainWindowClient.RefreshFeedDisplayThreadSafe() {
            if ( FeedTree.InvokeRequired ) {
                RefreshFeedDisplayCallback d = new RefreshFeedDisplayCallback( RefreshDisplayHelper );
                this.Invoke( d );
            } else {
                RefreshFeedDisplay();
            }
        }

        void IMainWindowClient.SetRightStatusTextThreadSafe( string text ) {
            if ( MainStatusBar.InvokeRequired ) {
                SetStatusRightTextCallback d = new SetStatusRightTextCallback( SetStatusRightText );
                this.Invoke( d, new object[] { text } );
            } else {
                statusBarPanelRight.Text = text;
            }
        }

        void IMainWindowClient.SetSyncIsOnGoingFlag(bool value) {
            m_IsCustomFeedSyncOnGoing = value;
        }

        private void menuItemLatestNews_Click( object sender, EventArgs e ) {
            try {
                Process.Start( "http://www.newsworm.net/news/" );
            } catch ( Exception ex ) {
                new MyMessageBoxError( ex.Message, ex.StackTrace ).ShowDialog();
            }
        }

        private void menuItemTutorial_Click( object sender, EventArgs e ) {
            try {
                Process.Start( "http://www.newsworm.net/help/" );
            } catch ( Exception ex ) {
                new MyMessageBoxError( ex.Message, ex.StackTrace ).ShowDialog();
            }
        }

        private void menuItemAdvanced_Popup( object sender, EventArgs e ) {
            if ( Properties.Settings.Default.ActivateScripts ) {
                menuItemScripting.Enabled = true;
                menuItemScriptManager.Enabled = true;
            } else {
                menuItemScripting.Enabled = false;
                menuItemScriptManager.Enabled = false;
            }
        }

        private void menuItemScriptManager_Click( object sender, EventArgs e ) {
            ScriptsDialog dlg = new ScriptsDialog( ref m_ScriptManager,
              new Point( this.Location.X + ( this.Width - 740 ) / 2,
                                                                   this.Location.Y + ( this.Height - 580 ) / 2 ) );

            dlg.SetTabPage( 1 );
            dlg.Show();
        }

        //Scripting
        private void menuItem4_Click( object sender, EventArgs e ) {
            try {
                Process.Start( "http://www.newsworm.net/help/#scripting" );
            } catch ( Exception ex ) {
                new MyMessageBoxError( ex.Message, ex.StackTrace ).ShowDialog();
            }
        }

        private void menuItemHostOnWebServer_Click( object sender, EventArgs e ) {
            StartStopWebServerForFeed( FeedTree.SelectedNode );
        }

        private void StartStopWebServerForFeed( TreeNode node ) {
            this.Cursor = Cursors.WaitCursor;
            if ( node != null && node.Level == 0 && node.Name != "fav" ) {
                Feed f = m_FeedManager.GetFeedByTitle( node.Name );
                if ( f != null ) {
                    if ( f.WebServerRunning ) {
                        f.StopWebServer();
                    } else {
                        string url = f.StartWebServer();
                        if ( url != null ) {
                            Clipboard.SetText( url );
                            statusBarPanelRight.Text = "Hosting url copied to clipboard";
                            m_TimerStatusBar.Start();
                        }
                    }
                }
            }
            this.Cursor = Cursors.Default;
        }

        internal void m_TimerStatusBar_Tick( object sender, EventArgs e ) {
            statusBarPanelRight.Text = "";
            m_TimerStatusBar.Stop();
        }

        private void menuItemForum_Click( object sender, EventArgs e ) {
            try {
                Process.Start( "http://www.newsworm.net/forum/" );
            } catch {
                Console.WriteLine( "Unable to launch an url." );
            }
        }

        private void menuItemMarkAllAsRead_Click( object sender, EventArgs e ) {
            foreach ( TreeNode node in FeedTree.Nodes ) {
                foreach ( TreeNode SubNode in node.Nodes ) {
                    MarkAsRead( SubNode );
                }
            }
        }

        
    }
}
